/**
 * 
 */
package controller;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import metier.ChargerCorpus;
import metier.ChargerFichier;
import metier.FiltreMetier;

/**
 * @author xavier
 * 
 */
public class MatriceDocMot {
	public final static Double BASE_DIX = 10.0;

	/**
	 * Applique la méthode matriceDocMotFichierController sur chaque texte.
	 * 
	 * @param nomCorpus
	 *            Le nom du corpus sous fichiersOriginaux
	 * @param tailleMini
	 *            La taille minimum des mots gardés.
	 * @return La matrice document mot pour tous les textess du corpus
	 * @throws IOException
	 *             Problèmes à l'ouverture d'un fichier.
	 */
	public static Map<String, Map<String, Integer>> matriceDocMotCorpusController(
			String nomCorpus, Integer tailleMini) throws IOException {
		List<String> listeDesTextes = ChargerCorpus.lireCorpus(nomCorpus);
		Integer compteur = 0;
		Map<String, Map<String, Integer>> matriceDocMotCorpus = new HashMap<String, Map<String, Integer>>();
		for (String texteTravail : listeDesTextes) {
			matriceDocMotCorpus.put(
					nomCorpus + compteur,
					matriceDocMotFichierController("fichiersOriginaux/"
							+ nomCorpus + "/" + texteTravail, tailleMini));
			++compteur;
		}
		return matriceDocMotCorpus;
	}

	/**
	 * Methode qui analyse un texte d'un corpus et qui produit la matrice
	 * document mot
	 * 
	 * @param nomFichier
	 *            Le nom du fichier et son emplacement sous fichiersOriginaux
	 * @param tailleMini
	 *            La taille minimum des mots à garder
	 * @return La matrice document mot
	 * @throws IOException
	 *             Problème à l'ouverte d'un fichier
	 */
	public static Map<String, Integer> matriceDocMotFichierController(
			String nomFichier, Integer tailleMini) throws IOException {
		// Créer la map de retour
		Map<String, Integer> mapRetour;
		String texteTravail = ChargerFichier.lireFichier(nomFichier);
		List<String> listeDeTravail = transformationEnList(texteTravail);
		// TODO Apliquer les filtres
		FiltreMetier filtreUn = new FiltreMetier();
		listeDeTravail = filtreUn.accent(listeDeTravail);
		listeDeTravail = filtreUn.minuscule(listeDeTravail);
		listeDeTravail = filtreUn.normalisation(listeDeTravail);
		listeDeTravail = filtreUn.adjectifPossessif(listeDeTravail);
		listeDeTravail = filtreUn.motTailleN(listeDeTravail, 3);
		listeDeTravail = filtreUn.lemmatisation(listeDeTravail);
		mapRetour = fabriquerMatriceDocMotFichier(listeDeTravail);
		return mapRetour;

	}

	/**
	 * Transforme une String en List de String. Le string est découpé avec les
	 * espaces.
	 * 
	 * @param contenuFichier
	 *            Le String à découper
	 * @return Le string découpé.
	 */
	private static List<String> transformationEnList(String contenuFichier) {
		String[] stringApresSplit = contenuFichier.trim().split(" ");
		List<String> liste = new ArrayList<String>();
		for (int index = 0; index < stringApresSplit.length; index++) {
			liste.add(stringApresSplit[index]);
		}
		return liste;

	}

	/**
	 * Parcours la liste de String et créer une HashMap avec comme index le
	 * string et comme valeur le nombre d'apparition.
	 * 
	 * @param contenuFichier
	 *            La list de string qui sert à créer la matrice doc/mot
	 * @return La matrice doc/mot
	 */
	public static Map<String, Integer> fabriquerMatriceDocMotFichier(
			List<String> contenuFichier) {
		Map<String, Integer> mapDocMotFichier = new HashMap<String, Integer>();
		for (String temp : contenuFichier) {
			Integer intTemp = mapDocMotFichier.get(temp);
			if (intTemp == null || intTemp == 0) {
				intTemp = 0;
			}
			mapDocMotFichier.put(temp, ++intTemp);
		}
		return mapDocMotFichier;
	}

	/**
	 * Fonction qui retourne la matrice TF/IDF en fonction d'une matrice mot/doc
	 * sur un corpus
	 * 
	 * @param matriceDocMot
	 *            La matrice DocMot qui a été faite sur un corpus
	 * @return La matrice TF/IDF de la matrice doc/mot passée en paramètre
	 */
	public static Map<String, Map<String, Double>> matriceTFTDF(
			Map<String, Map<String, Integer>> matriceDocMot) {
		// Le nombre de document de la matrice doc/mot
		Integer nombreDeDocument = matriceDocMot.size();
		// La nouvelle matrice qui contiendra le TF/IDF
		Map<String, Map<String, Double>> matriceTFIDF = new HashMap<String, Map<String, Double>>();
		// La map qui contient le nombre de documents ou le mot apparait dans le
		// corpus
		Map<String, Integer> nombreDocApparition = new HashMap<String, Integer>();
		for (Entry<String, Map<String, Integer>> entry : matriceDocMot
				.entrySet()) {
			for (Entry<String, Integer> entrysecond : entry.getValue()
					.entrySet()) {
				if (!nombreDocApparition.containsKey(entrysecond.getKey())) {
					nombreDocApparition.put(entrysecond.getKey(), 1);
				} else {
					nombreDocApparition.put(entrysecond.getKey(),
							nombreDocApparition.get(entrysecond.getKey()) + 1);
				}
			}
		}
		for (Entry<String, Map<String, Integer>> entry : matriceDocMot
				.entrySet()) {
			Map<String, Double> mapTravail = new HashMap<String, Double>();
			for (Entry<String, Integer> entrysecond : entry.getValue()
					.entrySet()) {
//				System.out.println(entrysecond.getKey()
//						+ " "
//						+ nombreDeDocument.doubleValue()
//						+ "   "
//						+ nombreDocApparition.get(entrysecond.getKey())
//								.doubleValue());
				Double doub = entrysecond.getValue()
						* Math.log(nombreDeDocument.doubleValue()
								/ nombreDocApparition.get(entrysecond.getKey())
										.doubleValue());
				mapTravail.put(entrysecond.getKey(), doub);
			}
			matriceTFIDF.put(entry.getKey(), mapTravail);
		}
		return matriceTFIDF;
	}

	public static void main(String[] args) throws IOException {
		Map<String, Integer> map = matriceDocMotFichierController(
				"fichiersOriginaux/testFoot/testFoot5.txt", 3);
		// for (Entry<String, Integer> entrysecond : map.entrySet()) {
		// System.out.println("Key " + entrysecond.getKey() + " Value "
		// + entrysecond.getValue()+" FIN");
		// }
		Map<String, Map<String, Integer>> mapD = matriceDocMotCorpusController(
				"testFoot", 3);
		// for (Entry<String, Map<String, Integer>> entry : mapD.entrySet()) {
		// Map<String, Integer> mapTravail = new HashMap<String, Integer>();
		// for (Entry<String, Integer> entrysecond : entry.getValue()
		// .entrySet()) {
		// System.out.println("Key " + entrysecond.getKey() + " Value "
		// + entrysecond.getValue());
		// }
		// }
		Map<String, Map<String, Double>> mapDeux = matriceTFTDF(mapD);
		// for (Entry<String, Map<String, Double>> entry : mapDeux.entrySet()) {
		// Map<String, Double> mapTravail = new HashMap<String, Double>();
		// for (Entry<String, Double> entrysecond : entry.getValue()
		// .entrySet()) {
		// System.out.println("Key " + entrysecond.getKey() + " Value "
		// + entrysecond.getValue());
		// }
		// }
	}
}